import { DefaultOptons, TrackerConfig, initOptions } from "../types/index";
import { createHistoryEvent } from "../utils/pv";

const MouseEventList: string[] = [
  // 按钮事件
  "click",
  "dblclick",
  "contextmenu",
  "mousedown",
  "mouseup",
  "mouseenter",
  "mouseout",
  "mouseover",
];

export default class Tracker {
  public data: initOptions;
  constructor(options: initOptions) {
    this.data = Object.assign(this.initDef(), options);
    this.installTracker();
    console.log(this.data);
  }

  private initDef(): DefaultOptons {
    window.history["pushState"] = createHistoryEvent("pushState");
    window.history["replaceState"] = createHistoryEvent("replaceState");
    return <DefaultOptons>{
      sdkVersion: TrackerConfig.version,
      historyTracker: false,
      hashTracker: false,
      domTracker: false,
      jsError: false,
    };
  }

  // 设置用户id
  public setUserId<T extends DefaultOptons["uuid"]>(uuid: T) {
    this.data.uuid = uuid;
  }

  // 透传值
  public setExtra<T extends DefaultOptons["extra"]>(extra: T) {
    this.data.extra = extra;
  }

  // 手动上报
  public sendTracker<T>(data: T) {
    this.reportTracker(data);
  }

  // 按钮带有target-key的上报
  private targetKeyRpeort() {
    MouseEventList.forEach((ev) => {
      window.addEventListener(ev, (e) => {
        const target = e.target as HTMLElement;
        const targetKey = target.getAttribute("target-key");
        if (targetKey) {
          this.reportTracker({ event: ev, targetKey });
        }
      });
    });
  }

  private captureEvents<T>(
    mouseEventList: string[],
    targetKey: string,
    data?: T
  ) {
    mouseEventList.forEach((event) => {
      window.addEventListener(event, () => {
        console.log("监听到了");
        this.reportTracker({ event, targetKey, data });
      });
    });
  }

  private installTracker() {
    // 如果用户开启了historyTracker
    if (this.data.historyTracker) {
      this.captureEvents(
        ["pushState", "replaceState", "popstate"],
        "history-pv"
      );
    }
    // 如果用户开启了hashTracker
    if (this.data.hashTracker) {
      this.captureEvents(["hashchange"], "hash-pv");
    }

    // 如果用户开启了domTracker
    if (this.data.domTracker) {
      this.targetKeyRpeort();
    }

    // 如果用户开启了jsError
    if (this.data.jsError) {
      console.log("hahahhahaha,jserror");

      this.jsErrorReport();
      this.promiseErrorReport();
    }
  }

  // js error 上报
  private jsErrorReport() {
    // window.addEventListener("error", (e) => {
    //   console.log(e);
    //   this.sendTracker({
    //     event: "error",
    //     targetKey: "message",
    //     message: e.message,
    //   });
    // });
    window.onerror = (message, source, line, col, error) => {
      console.log(message, source, line, col, error);

      this.sendTracker({
        event: "error",
        targetKey: "message",
        message: message,
      });
    };
  }

  // promise error 上报
  private promiseErrorReport() {
    window.addEventListener("unhandledrejection", (event) => {
      this.sendTracker({
        event: "promise",
        targetKey: "reject",
        message: event.reason,
      });
    });
  }

  // 使用navigator.sendBeacon这个去做上报，这个上报的机制跟XMLHttpRequest不一样，
  // 它是异步的，不会阻塞页面的卸载，即使页面关闭了，也会继续发送请求
  private reportTracker<T>(data: T) {
    const params = Object.assign(this.data, data, {
      time: new Date().getTime(),
    });
    let headers = {
      type: "application/x-www-form-urlencoded",
    };
    let blob = new Blob([JSON.stringify(params)], headers);
    navigator.sendBeacon(this.data.requestUrl, blob);
  }
}
